package com.zystudio.func.net;


import java.util.concurrent.LinkedBlockingQueue;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * 线程池管理类
 */
public final class ThreadPoolManager {

    private static final class MInstanceHolder {
        static final ThreadPoolManager mInstance = new ThreadPoolManager();
    }

    public static ThreadPoolManager getInstance() {
        return MInstanceHolder.mInstance;
    }

    /**
     * 核心线程数
     */
    private final int corePoolSize;
    /**
     * 最大线程数
     */
    private final int maximumPoolSize;
    private final long keepAliveTime = 60L;
    private ThreadPoolExecutor executor;

    private ThreadPoolManager() {
        //本身并发量不高，避免设置太大，导致cpu无法分配
        corePoolSize = 4;
        maximumPoolSize = 10;
        executor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize,
                keepAliveTime,
                TimeUnit.SECONDS,
                new LinkedBlockingQueue<Runnable>(200),
                new DefaultThreadFactory(Thread.NORM_PRIORITY, "zy-pool-%d"),
                new ThreadPoolExecutor.AbortPolicy());
    }

    public void execute(Runnable runnable) {
        if (executor == null) {
            executor = new ThreadPoolExecutor(corePoolSize, maximumPoolSize,
                    keepAliveTime,
                    TimeUnit.SECONDS,
                    new LinkedBlockingQueue<Runnable>(200),
                    new DefaultThreadFactory(Thread.NORM_PRIORITY, "zy-pool-%d"),
                    new ThreadPoolExecutor.AbortPolicy());
        }
        if (runnable != null) {
            executor.execute(runnable);
        }
    }

    public void remove(Runnable runnable) {
        if (runnable != null) {
            executor.remove(runnable);
        }
    }

    /**
     * 创建线程的工厂，设置线程的优先级，group，以及命名
     */
    private static class DefaultThreadFactory implements ThreadFactory {
        //线程池的计数
        private static final AtomicInteger poolNumber = new AtomicInteger(1);
        private final AtomicInteger threadNumber = new AtomicInteger(1);
        private final ThreadGroup group;
        private final String namePrefix;
        private final int threadPriority;

        DefaultThreadFactory(int threadPriority, String threadNamePrefix) {
            this.threadPriority = threadPriority;
            this.group = Thread.currentThread().getThreadGroup();
            namePrefix = threadNamePrefix + poolNumber.getAndIncrement() + "-thread-";
        }

        @Override
        public Thread newThread(Runnable r) {
            Thread t = new Thread(group, r, namePrefix + threadNumber.getAndIncrement(), 0);
            if (t.isDaemon()) {
                t.setDaemon(false);
            }
            t.setPriority(threadPriority);
            return t;
        }

    }


}
